/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.service.impl;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.req.ListDictItemRequest;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.FolderClient;
import com.xy.biz.fd.client.RepositoryClient;
import com.xy.biz.fd.domain.req.document.GetDocumentRequest;
import com.xy.biz.fd.domain.req.document.ListDocumentRequest;
import com.xy.biz.fd.domain.req.folder.ListFolderRequest;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.fd.domain.resp.GetRepositoryResponse;
import com.xy.biz.ts.client.LearnRecordClient;
import com.xy.biz.ts.domain.req.ListLearnRecordRequest;
import com.xy.biz.ts.domain.resp.GetLearnRecordResponse;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.client.UserGroupClient;
import com.xy.biz.uc.domain.constant.RoleConstant;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.req.IsInRoleRequest;
import com.xy.biz.uc.domain.req.ListUserGroupByIdsRequest;
import com.xy.biz.xd.domain.bo.DocumentFlowBO;
import com.xy.biz.xd.domain.bo.DocumentReleaseBO;
import com.xy.biz.xd.domain.bo.DocumentReleaseCheckBO;
import com.xy.biz.xd.domain.enums.DocumentFlowBatchTypeEnum;
import com.xy.biz.xd.domain.enums.DocumentReleaseReceiveTypeEnum;
import com.xy.biz.xd.domain.enums.DocumentReleaseStatusEnum;
import com.xy.biz.xd.domain.query.DocumentFlowQuery;
import com.xy.biz.xd.domain.query.DocumentReleaseCheckQuery;
import com.xy.biz.xd.domain.query.DocumentReleaseQuery;
import com.xy.biz.xd.domain.req.*;
import com.xy.biz.xd.domain.resp.*;
import com.xy.biz.xd.manager.DocumentFlowManager;
import com.xy.biz.xd.manager.DocumentReleaseCheckManager;
import com.xy.biz.xd.manager.DocumentReleaseManager;
import com.xy.biz.xd.service.DocumentReleaseService;
import com.xy.lang.domain.KeyValue;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Triple;
import com.xy.lang.util.CalendarUtils;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.util.BeanUtilsEx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 *
 *
 * @author wcs
 * @date 2021-3-4
 */
@Service
public class DocumentReleaseServiceImpl implements DocumentReleaseService {

    @Autowired
    private UserClient userClient;
    @Autowired
    private DictClient dictClient;
    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private UserGroupClient userGroupClient;
    @Autowired
    private RepositoryClient repositoryClient;
    @Autowired
    private LearnRecordClient learnRecordClient;
    @Autowired
    private DocumentFlowManager documentFlowManager;
    @Autowired
    private DocumentReleaseManager documentReleaseManager;
    @Autowired
    private DocumentReleaseCheckManager documentReleaseCheckManager;

    /**
     * 签收处理
     *
     * @param query 查找条件
     */
    @Override
    public List<DocumentReleaseBO> signInProcessing(DocumentReleaseQuery query) {
        return listDocumentRelease(query);
    }

    /**
     * 生效处理
     *
     * @param query 查找条件
     */
    @Override
    public List<DocumentReleaseBO> effectiveProcessing(DocumentReleaseQuery query) {
        query.setEffectiveFlag(true);
        query.setReceiveTypeList(Arrays.asList(DocumentReleaseReceiveTypeEnum.USER_RECEIVE.getCode(),
                DocumentReleaseReceiveTypeEnum.USER_GROUP_RECEIVE.getCode()));
        return listAllDocumentRelease(query);
    }

    @Override
    public List<DocumentReleaseBO> listAllDocumentRelease(DocumentReleaseQuery query) {
        List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listAllDocumentRelease(query);
        return buildDocumentRelease(documentReleaseBOList);
    }

    /**
     * 查找多个
     *
     * @param query 查找条件
     */
    @Override
    public List<DocumentReleaseBO> listDocumentRelease(DocumentReleaseQuery query) {
        List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listDocumentRelease(query);
        return buildDocumentRelease(documentReleaseBOList);
    }

    private List<DocumentReleaseBO> buildDocumentRelease(List<DocumentReleaseBO> documentReleaseBOList) {
        if (CollectionUtils.isEmpty(documentReleaseBOList)) {
            return Collections.emptyList();
        }
        Set<Long> documentIdList = new HashSet<>();
        Set<Long> createUserIds = new HashSet<>();
        Set<Long> documentReleaseIdList = new HashSet<>();
        //Set<String> documentCodeSet = new HashSet<>();
        List<DocumentReleaseBO> filteredDocumentReleaseBOList = new ArrayList<>();
        for (DocumentReleaseBO documentReleaseBO : documentReleaseBOList) {
            //if (documentCodeSet.add(documentReleaseBO.getDocumentCode())) {
            documentIdList.add(documentReleaseBO.getDocumentId());
            documentReleaseIdList.add(documentReleaseBO.getDocumentReleaseId());
            createUserIds.add(documentReleaseBO.getCreateUserId());
            filteredDocumentReleaseBOList.add(documentReleaseBO);
            //}
        }
        if (CollectionUtils.isEmpty(documentIdList)) {
            return Collections.emptyList();
        }
        //获取发行知识库信息
        Result<GetRepositoryResponse> releaseRepositoryInfo = repositoryClient.getReleaseRepositoryInfo();
        if (!releaseRepositoryInfo.wasSuccess()) {
            return Collections.emptyList();
        }
        GetRepositoryResponse repositoryInfoData = releaseRepositoryInfo.getData();
        Map<Long, DocumentReleaseCheckBO> documentReleaseCheckGroup = documentReleaseCheckManager.listDocumentReleaseCheckByRepositoryIdAndDocumentReleaseId(repositoryInfoData.getRepositoryId(), documentReleaseIdList)
                .stream().collect(Collectors.toMap(DocumentReleaseCheckBO::getDocumentReleaseId, e -> e, (e1, e2) -> e2));

        Map<Long, GetLearnRecordResponse> learnRecordResponseMap = ResultUtils.get(learnRecordClient.listLearnRecord(ListLearnRecordRequest.builder().lessonIds(new ArrayList<>(documentIdList)).build()))
                .stream().collect(Collectors.toMap(GetLearnRecordResponse::getLessonId, e -> e, (e1, e2) -> e2));
        filteredDocumentReleaseBOList.forEach(e -> {
            DocumentReleaseCheckBO documentReleaseCheck = documentReleaseCheckGroup.get(e.getDocumentReleaseId());
            if (Objects.nonNull(documentReleaseCheck)) {
                e.setSignForStatus(1);
                e.setSignForTime(documentReleaseCheck.getCreateTime());
            } else {
                e.setSignForStatus(0);
                e.setSignForTime(null);
            }
            if (!CollectionUtils.isEmpty(learnRecordResponseMap)) {
                GetLearnRecordResponse getLearnRecordResponse = learnRecordResponseMap.get(e.getDocumentId());
                if (Objects.nonNull(getLearnRecordResponse)) {
                    e.setSelfStudy(1);
                } else {
                    e.setSelfStudy(0);
                }
            } else {
                e.setSelfStudy(0);
            }
            //设置签收时间(n分钟前)
            e.setSignForTimeString(CalendarUtils.getDeadlineString(e.getSignForTime(), LocalDateTime.now()));
        });
        Map<Long, String> map = ResultUtils.get(userClient.listUserById(createUserIds)).stream().collect(Collectors.toMap(UserDTO::getUserId, UserDTO::getUserName));
        Map<Long, String> documentNameMap = ResultUtils.get(documentClient.listDocumentById(documentIdList)).stream().collect(Collectors.toMap(GetDocumentResponse::getDocumentId, GetDocumentResponse::getFileExtension));
        filteredDocumentReleaseBOList.forEach(d -> {
            d.setFileExtension(documentNameMap.get(d.getDocumentId()));
            d.setCreateUserGroupName(map.get(d.getCreateUserId()));
        });
        filteredDocumentReleaseBOList.sort((m1, m2) -> m2.getCreateTime().compareTo(m1.getCreateTime()));
        return filteredDocumentReleaseBOList;
    }


    /**
     * 查看签收情况
     * @param request 查找条件
     */
    @Override
    public Result<?> DocumentReleaseCheck(GetDocumentReleaseCheckStatusRequest request) {
        Result<Triple<DocumentFlowBO, List<DocumentReleaseByUserGroupResponse>, List<DocumentReleaseByUserResponse>>> releaseUserAndUserGroup =
                getReleaseUserAndUserGroup(request.getDocumentFlowId());
        if (!releaseUserAndUserGroup.wasSuccess()) {
            return releaseUserAndUserGroup;
        }
        Triple<DocumentFlowBO, List<DocumentReleaseByUserGroupResponse>, List<DocumentReleaseByUserResponse>> data =
                releaseUserAndUserGroup.getData();
        return Result.success(GetDocumentReleaseStatusResponse.builder()
                .documentFlowId(request.getDocumentFlowId())
                .documentId(data.getValue1().getDocumentId())
                .documentName(data.getValue1().getDocumentName())
                .groupResponses(data.getValue2())
                .userResponses(data.getValue3())
                .build());
    }

    @Override
    public Result<?> getTrainByDocumentFlow(Long documentFlowId) {
        Result<Triple<DocumentFlowBO, List<DocumentReleaseByUserGroupResponse>, List<DocumentReleaseByUserResponse>>> releaseUserAndUserGroup =
                getReleaseUserAndUserGroup(documentFlowId);
        if (!releaseUserAndUserGroup.wasSuccess()) {
            return releaseUserAndUserGroup;
        }
        Triple<DocumentFlowBO, List<DocumentReleaseByUserGroupResponse>, List<DocumentReleaseByUserResponse>> data =
                releaseUserAndUserGroup.getData();
        List<DocumentFlowBO> documentFlowBOList =
                documentFlowManager.listDocumentFlow(DocumentFlowQuery.max().parentDocumentFlowId(documentFlowId).build());
        if (CollectionUtils.isEmpty(documentFlowBOList)) {
            documentFlowBOList = new ArrayList();
            documentFlowBOList.add(data.getValue1());
        }
        List<GetDocumentFlowNewAndModifyResponse> getDocumentFlowNewAndModifyResponses = BeanUtilsEx.copyPropertiesForNewList(documentFlowBOList, GetDocumentFlowNewAndModifyResponse::new);
        return Result.success(GetTrainByDocumentFlowResponse.builder()
                .parentDocumentFlowNewAndModify(BeanUtilsEx.copyProperties(data.getValue1(), GetDocumentFlowNewAndModifyResponse::new))
                .documentFlowNewAndModifySubFile(getDocumentFlowNewAndModifyResponses)
                .groupResponses(data.getValue2())
                .userResponses(data.getValue3())
                .build());
    }

    private Result<Triple<DocumentFlowBO, List<DocumentReleaseByUserGroupResponse>, List<DocumentReleaseByUserResponse>>> getReleaseUserAndUserGroup(Long documentFlowId) {
        //通过流程Id获取流程
        DocumentFlowBO documentFlow = documentFlowManager.getDocumentFlow(documentFlowId);
        if (Objects.isNull(documentFlow)) {
            return Result.ofNotFound();
        }
        //获取文件发行列表
        List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listDocumentRelease(
                DocumentReleaseQuery.max()
                        .documentFlowId(documentFlow.getDocumentFlowId())
                        .status(DocumentReleaseStatusEnum.RELEASE.getCode()).build());
        if (CollectionUtils.isEmpty(documentReleaseBOList)) {
            return Result.ofNotFound();
        }
        //区分部门和个人
        List<DocumentReleaseBO> documentFilterByUserGroup = new ArrayList<>();
        Set<Long> documentReleaseReceiveByUserGroupIdSet = new HashSet<>();
        //发行给个人
        List<DocumentReleaseBO> documentFilterByUser = new ArrayList<>();
        documentReleaseBOList.forEach(e -> {
            if (e.getReceiveType().equals(DocumentReleaseReceiveTypeEnum.USER_RECEIVE.getCode())) {
                documentFilterByUser.add(e);
            } else if (e.getReceiveType().equals(DocumentReleaseReceiveTypeEnum.USER_GROUP_RECEIVE.getCode())) {
                documentReleaseReceiveByUserGroupIdSet.add(e.getReceiveId());
                documentFilterByUserGroup.add(e);
            }
        });

        List<DocumentReleaseByUserGroupResponse> documentReleaseByUserGroupResponseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(documentFilterByUserGroup)) {
            //key:团队Id
            Map<Long, List<DocumentReleaseBO>> groupsMap = documentFilterByUserGroup.stream().collect(Collectors.groupingBy(DocumentReleaseBO::getReceiveId));
            documentFilterByUserGroup.forEach(e -> {
                DocumentReleaseByUserGroupResponse resp = new DocumentReleaseByUserGroupResponse();
                resp.setId(e.getReceiveId());
                documentReleaseByUserGroupResponseList.add(resp);
            });
            userGroupClient.buildByUserGroup(documentReleaseByUserGroupResponseList,
                    documentReleaseByUserGroupResponseList.stream().map(DocumentReleaseByUserGroupResponse::getId).collect(Collectors.toList()),
                    DocumentReleaseByUserGroupResponse::getId,
                    (g, userGroupDTO) -> g.setLabel(userGroupDTO.getUserGroupName()));
            //接受对象Id
            //查找团队下的成员
            Map<Long, List<UserDTO>> userDTOMap = new HashMap<>(ResultUtils.get(userClient.listUserByUserGroup(
                    ListUserGroupByIdsRequest.builder().groupIds(documentReleaseReceiveByUserGroupIdSet).build()))
                    .stream().collect(Collectors.groupingBy(u -> u.getUserGroup().getId())));
            documentReleaseByUserGroupResponseList.forEach(e -> {
                if (userDTOMap.containsKey(e.getId())) {
                    List<UserDTO> userDTOS = userDTOMap.get(e.getId());
                    //获取发行Id
                    Set<Long> documentReleaseIdSet = groupsMap.get(e.getId()).stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
                    List<DocumentReleaseByUserResponse> documentReleaseByUserResponseList = buildCheckUsers(userDTOS, documentReleaseIdSet);
                    e.setUserResponses(documentReleaseByUserResponseList);
                }
            });
        }
        List<DocumentReleaseByUserResponse> documentReleaseByUserResponseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(documentFilterByUser)) {
            Set<Long> documentReleaseIdSet = documentFilterByUser.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
            Set<Long> userIdSet = documentFilterByUser.stream().map(DocumentReleaseBO::getReceiveId).collect(Collectors.toSet());
            List<UserDTO> userDTOS = ResultUtils.get(userClient.listUserById(userIdSet));
            documentReleaseByUserResponseList = buildCheckUsers(userDTOS, documentReleaseIdSet);
        }
        return Result.success(new Triple<>(documentFlow, documentReleaseByUserGroupResponseList, documentReleaseByUserResponseList));
    }

    /**
     * 查看签收情况
     *
     * @param documentReleaseIdS 查找条件
     */
    @Override
    public List<DocumentReleaseCheckBO> listDocumentReleaseCheck(Collection<Long> documentReleaseIdS) {
        return documentReleaseCheckManager.listDocumentReleaseCheckByReleaseId(documentReleaseIdS);
    }


    @Override
    public int countDocumentRelease(DocumentReleaseQuery query) {
        return documentReleaseManager.countDocumentRelease(query);
    }

    @Override
    public int countAllDocumentRelease(DocumentReleaseQuery query) {
        return documentReleaseManager.countAllDocumentRelease(query);
    }

    /**
     * 生效开关打开
     *
     * @param query
     */
    @Override
    public Result<?> takeEffectDocumentRelease(DocumentReleaseQuery query) {
        DocumentReleaseBO documentRelease = documentReleaseManager.getDocumentRelease(query.getDocumentReleaseId());
        Set<Long> documentReleaseBOIds = documentReleaseManager.listDocumentReleaseByDocumentCode(documentRelease.getDocumentCode()).stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
        query.setDocumentReleaseIdS(documentReleaseBOIds);
        DocumentReleaseBO documentReleaseBO = documentReleaseManager.takeEffectDocumentRelease(query);
        if (LocalDate.now().isAfter(documentRelease.getEffectDate())) {
            documentReleaseManager.takeEffectFlagDocumentReleaseById(query);
        }
        return Result.success(documentReleaseBO);
    }

    /**
     * 生效开关关闭
     *
     * @param query
     */
    @Override
    public Result<?> loseEffectDocumentRelease(DocumentReleaseQuery query) {
        DocumentReleaseBO documentRelease = documentReleaseManager.getDocumentRelease(query.getDocumentReleaseId());
        if (LocalDate.now().isBefore(documentRelease.getEffectDate())) {
            Set<Long> documentReleaseBOIds = documentReleaseManager.listDocumentReleaseByDocumentCode(documentRelease.getDocumentCode()).stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
            query.setDocumentReleaseIdS(documentReleaseBOIds);
            documentReleaseManager.loseEffectDocumentRelease(query);
            return Result.success(documentReleaseManager.loseEffectFlagDocumentReleaseById(query));
        }
        return Result.fail("", "文档已生效，无法执行此操作！");
    }

    @Override
    public Result<?> addDocumentReleaseReceive(SaveDocumentReleaseReceiveRequest request) {
        List<DocumentReleaseBO> existingDocumentReleaseBOList = documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max().documentFlowId(request.getDocumentFlowId()).build());
        if (CollectionUtils.isEmpty(existingDocumentReleaseBOList)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        DocumentReleaseBO existingDocumentRelease = existingDocumentReleaseBOList.get(0);
        List<DocumentReleaseBO> documentReleaseBOList = new ArrayList<>();
        request.getReceiveIdList().forEach(e -> {
            DocumentReleaseBO documentReleaseBO = new DocumentReleaseBO();
            BeanUtilsEx.copyProperties(existingDocumentRelease, documentReleaseBO);
            documentReleaseBO.setDocumentReleaseId(null);
            documentReleaseBO.setReceiveId(e);
            documentReleaseBO.setReceiveType(request.getReceiveType());
            documentReleaseBOList.add(documentReleaseBO);
        });
        if (CollectionUtils.isEmpty(documentReleaseBOList)) {
            return Result.ofNotFound();
        }
        int row = documentReleaseManager.saveAllDocumentRelease(documentReleaseBOList);
        if (row > 0) {
            return Result.success();
        }
        return Result.fail();
    }

    @Override
    @Transactional
    public Result<?> reallocate(Collection<String> collection) {
        for (String documentCode : collection) {
            List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listDocumentReleaseByDocumentCode(documentCode);
            if (CollectionUtils.isEmpty(documentReleaseBOList)) {
                continue;
            }
            DocumentReleaseBO documentReleaseBO = documentReleaseBOList.get(0);
            documentReleaseCheckManager.deleteDocumentReleaseCheckByDocumentReleaseId(documentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet()));
            List<Long> userGroupIdList = new ArrayList<>();
            //选择接收部门Id
//            userGroupIdList.add(11L);
//            userGroupIdList.add(12L);
//            userGroupIdList.add(13L);
//            userGroupIdList.add(14L);
//            userGroupIdList.add(15L);
//            userGroupIdList.add(16L);
//            userGroupIdList.add(17L);
//              userGroupIdList.add(18L);
//              userGroupIdList.add(19L);
//              userGroupIdList.add(20L);
//              userGroupIdList.add(22L);
//            userGroupIdList.add(23L);
//            userGroupIdList.add(24L);
//            userGroupIdList.add(25L);
//            userGroupIdList.add(26L);
//            userGroupIdList.add(27L);
            List<DocumentReleaseBO> collect = documentReleaseBOList.stream().filter(e -> userGroupIdList.contains(e.getReceiveId()) && e.getReceiveType() == 1).collect(Collectors.toList());
            documentReleaseBOList.removeAll(collect);
            if (!CollectionUtils.isEmpty(documentReleaseBOList)) {
                Set<Long> collect1 = documentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
                collect1.forEach(e -> documentReleaseManager.deleteDocumentRelease(e));
            }
            List<DocumentReleaseBO> documentReleaseBOS = new ArrayList<>();
            if (CollectionUtils.isEmpty(collect) || collect.size() != userGroupIdList.size()) {
                if (!CollectionUtils.isEmpty(collect)) {
                    List<Long> collect1 = collect.stream().map(DocumentReleaseBO::getReceiveId).collect(Collectors.toList());
                    userGroupIdList.removeAll(collect1);
                }
                userGroupIdList.forEach(e -> {
                    DocumentReleaseBO documentReleaseBO1 = new DocumentReleaseBO();
                    BeanUtilsEx.copyProperties(documentReleaseBO, documentReleaseBO1);
                    documentReleaseBO1.setDocumentReleaseId(null);
                    documentReleaseBO1.setReceiveType(1);
                    documentReleaseBO1.setPermission(3);
                    documentReleaseBO1.setReceiveId(e);
                    documentReleaseBOS.add(documentReleaseBO1);
                });
            }
            if (!CollectionUtils.isEmpty(documentReleaseBOS)) {
                documentReleaseManager.saveAllDocumentRelease(documentReleaseBOS);
            }
        }
        return Result.success();
    }


    /**
     * 现行文件生效
     *
     * @param query 查找条件
     */
    @Override
    public Result<?> takeEffectFlagDocumentRelease(DocumentReleaseQuery query) {
        int row = documentReleaseManager.takeEffectFlagDocumentRelease(query);
        return Result.success(row);
    }


    @Override
    public Result<?> deleteDocumentReleaseReceive(SaveDocumentReleaseReceiveRequest request) {
        List<DocumentReleaseBO> existingDocumentReleaseBOList = documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max()
                .documentFlowId(request.getDocumentFlowId())
                .receiveIdList(request.getReceiveIdList())
                .receiveType(request.getReceiveType()).build());
        if (CollectionUtils.isEmpty(existingDocumentReleaseBOList)) {
            return Result.ofNotFound();
        }
        Set<Long> documentReleaseIdSet = existingDocumentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
        int row = documentReleaseManager.deleteDocumentRelease(documentReleaseIdSet);
        if (row > 0) {
            return Result.success();
        }
        return Result.fail();
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    @Override
    public Result<?> addDocumentReleaseReceiveList(SaveDocumentReleaseReceiveListRequest request) {
        List<DocumentReleaseBO> documentReleaseBOList;
        if (Objects.equals(true, request.getReleaseAllFlag())) {
            documentReleaseBOList =
                    documentReleaseManager.listAllDocumentRelease(DocumentReleaseQuery.max().build());
        } else {
            if (CollectionUtils.isEmpty(request.getDocumentCodeList())) {
                return Result.ofNotFound();
            }
            documentReleaseBOList =
                    documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max()
                            .documentCodeList(request.getDocumentCodeList())
                            .build());
            documentReleaseBOList = documentReleaseBOList.stream().filter(distinctByKey(DocumentReleaseBO::getDocumentCode)).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(documentReleaseBOList)) {
            return Result.ofNotFound();
        }
        Set<Long> userIdSet;
        Set<Long> userGroupIdSet;
        if (Objects.equals(DocumentReleaseReceiveTypeEnum.USER_RECEIVE.getCode(), request.getReceiveType())) {
            List<UserDTO> userDTOList = ResultUtils.getOrException(userClient.listUserById(request.getReceiveIdList()));
            userGroupIdSet = userDTOList.stream().filter(e -> Objects.nonNull(e.getUserGroup()))
                    .map(e -> e.getUserGroup().getId()).collect(Collectors.toSet());
            userIdSet = new HashSet<>(request.getReceiveIdList());
        } else {
            userGroupIdSet = new HashSet<>(request.getReceiveIdList());
            userIdSet = new HashSet<>(ResultUtils.getOrException(userClient.listUserIdByUserGroupId(request.getReceiveIdList())));
        }
        List<DocumentReleaseBO> receivedDocumentReleaseBOList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(userIdSet)) {
            receivedDocumentReleaseBOList.addAll(documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max()
                    .receiveIdList(new ArrayList<>(userIdSet))
                    .documentCodeList(request.getDocumentCodeList())
                    .receiveType(DocumentReleaseReceiveTypeEnum.USER_RECEIVE.getCode())
                    .build()));
        }
        if (!CollectionUtils.isEmpty(userGroupIdSet)) {
            receivedDocumentReleaseBOList.addAll(documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max()
                    .receiveIdList(new ArrayList<>(userGroupIdSet))
                    .documentCodeList(request.getDocumentCodeList())
                    .receiveType(DocumentReleaseReceiveTypeEnum.USER_GROUP_RECEIVE.getCode())
                    .build()));
        }
        Map<String, Map<Integer, Set<Long>>> existingReceiver = new HashMap<>();
        for (DocumentReleaseBO documentReleaseBO : receivedDocumentReleaseBOList) {
            Map<Integer, Set<Long>> receiveTypeGroup = existingReceiver.computeIfAbsent(documentReleaseBO.getDocumentCode(), (k) -> new HashMap<>());
            Set<Long> receiveIdSet =
                    receiveTypeGroup.computeIfAbsent(documentReleaseBO.getReceiveType(), (k) -> new HashSet<>());
            receiveIdSet.add(documentReleaseBO.getReceiveId());
        }
        List<DocumentReleaseBO> addDocumentReleaseList = new ArrayList<>();
        for (DocumentReleaseBO documentReleaseBO : documentReleaseBOList) {
            Map<Integer, Set<Long>> receiveTypeGroup = existingReceiver.get(documentReleaseBO.getDocumentCode());
            Set<Long> receiverIdSet = null;
            if (!CollectionUtils.isEmpty(receiveTypeGroup)) {
                receiverIdSet = receiveTypeGroup.get(request.getReceiveType());
            }
            for (Long e : request.getReceiveIdList()) {
                if (!CollectionUtils.isEmpty(receiverIdSet) && receiverIdSet.contains(e)) {
                    continue;
                }
                DocumentReleaseBO releaseBO = new DocumentReleaseBO();
                BeanUtilsEx.copyProperties(documentReleaseBO, releaseBO);
                releaseBO.setDocumentReleaseId(null);
                releaseBO.setReceiveId(e);
                releaseBO.setPermission(3);
                releaseBO.setReceiveType(request.getReceiveType());
                addDocumentReleaseList.add(releaseBO);
            }
        }
        if (CollectionUtils.isEmpty(addDocumentReleaseList)) {
            return Result.ofNotFound("数据已存在，请勿重复添加！");
        }
        int row = documentReleaseManager.saveAllDocumentRelease(addDocumentReleaseList);
        if (row > 0) {
            return Result.success();
        }
        return Result.fail();
    }

    /**
     * 现行文件失效
     *
     * @param query
     */
    @Override
    public Result<?> loseEffectFlagDocumentRelease(DocumentReleaseQuery query) {
        return Result.success(documentReleaseManager.loseEffectFlagDocumentRelease(query));
    }

    @Transactional
    @Override
    public Result<?> signForDocument(Long documentReleaseId) {
        //查询发行文件
        DocumentReleaseBO documentRelease = documentReleaseManager.getDocumentRelease(documentReleaseId);
        if (Objects.isNull(documentRelease)) {
            return Result.ofNotFound("发行文档不存在");
        }
        Result<GetRepositoryResponse> releaseRepositoryInfo = repositoryClient.getReleaseRepositoryInfo();
        if (!releaseRepositoryInfo.wasSuccess()) {
            return Result.ofNotFound("发行知识库初始化失败");
        }
        //发行知识库
        GetRepositoryResponse repositoryInfoData = releaseRepositoryInfo.getData();

        //查看是否已签收 发行知识库id + 文档id
        List<DocumentReleaseCheckBO> documentReleaseCheckBOList = documentReleaseCheckManager.listDocumentReleaseCheckByRepositoryIdAndSourceFolderId(DocumentReleaseCheckQuery
                .builder()
                .repositoryId(repositoryInfoData.getRepositoryId())
                .documentReleaseId(documentReleaseId)
                .build());

        if (!CollectionUtils.isEmpty(documentReleaseCheckBOList)) {
            return Result.ofNotFound("该文件已发行");
        }

        //查询文件详情
        GetDocumentRequest getDocumentRequest = GetDocumentRequest.builder().documentId(documentRelease.getDocumentId()).build();
        Result<GetDocumentResponse> documentResponseResult = documentClient.getDocument(getDocumentRequest);
        if (!documentResponseResult.wasSuccess()) {
            return Result.ofNotFound("文档不存在");
        }

        GetDocumentResponse documentResponse = documentResponseResult.getData();

        //发行知识库下文件夹id
        Long newFolderId = 0L;

        Long folderId = documentResponse.getFolderId();

        LocalDateTime now = LocalDateTime.now();
        DocumentReleaseCheckBO documentReleaseCheckBO = DocumentReleaseCheckBO.builder()
                .documentReleaseId(documentRelease.getDocumentReleaseId())
                .checkUserId(UserContextHolder.getUserId())
                .checkUserGroupId(UserContextHolder.getUserGroupId())
                .checkTime(now)
                .learnFlag(false)
                .folderId(newFolderId)
                .sourceFolderId(folderId)
                .repositoryId(repositoryInfoData.getRepositoryId())
                .tenantId(0L)
                .createUserId(UserContextHolder.getUserId())
                .createTime(now)
                .updateTime(now).build();
        int row = documentReleaseCheckManager.saveDocumentReleaseCheck(documentReleaseCheckBO);
        if (row > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    /**
     * 批量签收发行文档
     * @param request
     * @return
     */
    @Override
    public Result<?> signForDocumentBatch(SignDocumentReleaseRequest request) {
        //查询发行文件
        List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listDocumentReleaseByReleaseId(request.getDocumentReleaseIdList());
        if (CollectionUtils.isEmpty(documentReleaseBOList)) {
            return Result.ofNotFound("发行文档不存在");
        }
        Set<Long> documentReleaseIdSet = documentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
        Result<GetRepositoryResponse> releaseRepositoryInfo = repositoryClient.getReleaseRepositoryInfo();
        if (!releaseRepositoryInfo.wasSuccess()) {
            return Result.ofNotFound("发行知识库初始化失败");
        }
        //发行知识库
        GetRepositoryResponse repositoryInfoData = releaseRepositoryInfo.getData();

        Map<Long, DocumentReleaseCheckBO> documentReleaseCheckMap = documentReleaseCheckManager.listDocumentReleaseCheckByRepositoryIdAndDocumentReleaseId(repositoryInfoData.getRepositoryId(), documentReleaseIdSet).stream().collect(Collectors.toMap(DocumentReleaseCheckBO::getDocumentReleaseId, e -> e, (e1, e2) -> e2));

        //已发行
        List<DocumentReleaseBO> releasedDocumentReleaseBOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(documentReleaseCheckMap)) {
            releasedDocumentReleaseBOList = documentReleaseBOList.stream().filter(e -> documentReleaseCheckMap.containsKey(e.getDocumentReleaseId())).collect(Collectors.toList());
            documentReleaseBOList.removeAll(releasedDocumentReleaseBOList);
        }
        Set<Long> documentIdSet = documentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentId).collect(Collectors.toSet());
        Map<Long, GetDocumentResponse> documentResponseMap = ResultUtils.get(documentClient.listDocumentById(documentIdSet)).stream().collect(Collectors.toMap(GetDocumentResponse::getDocumentId, e -> e, (e1, e2) -> e2));
        if (CollectionUtils.isEmpty(documentResponseMap)) {
            return Result.ofNotFound("文档不存在");
        }
        List<DocumentReleaseBO> notExistDocumentReleaseBOList = new ArrayList<>();
        if (!documentResponseMap.keySet().containsAll(documentIdSet)) {
            documentIdSet.removeAll(documentResponseMap.keySet());
            notExistDocumentReleaseBOList = documentReleaseBOList.stream().filter(e -> documentIdSet.contains(e.getDocumentId())).collect(Collectors.toList());
        }
        //发行知识库下文件夹id
        Long newFolderId = 0L;
        LocalDateTime now = LocalDateTime.now();
        List<DocumentReleaseCheckBO> documentReleaseCheckBOList = new ArrayList<>();
        documentReleaseBOList.forEach(e -> {
            GetDocumentResponse documentResponse = documentResponseMap.get(e.getDocumentId());
            DocumentReleaseCheckBO documentReleaseCheckPO1 = DocumentReleaseCheckBO.builder()
                    .documentReleaseId(e.getDocumentReleaseId())
                    .checkUserId(UserContextHolder.getUserId())
                    .checkUserGroupId(UserContextHolder.getUserGroupId())
                    .checkTime(now)
                    .learnFlag(false)
                    .folderId(newFolderId)
                    .sourceFolderId(Objects.isNull(documentResponse) ? 0L : documentResponse.getFolderId())
                    .repositoryId(repositoryInfoData.getRepositoryId())
                    .tenantId(0L)
                    .createUserId(UserContextHolder.getUserId())
                    .createTime(now)
                    .updateTime(now).build();
            documentReleaseCheckBOList.add(documentReleaseCheckPO1);
        });
        int row = documentReleaseCheckManager.saveAllDocumentReleaseCheck(documentReleaseCheckBOList);
        if (row > 0) {
            if (!CollectionUtils.isEmpty(releasedDocumentReleaseBOList)) {
                return Result.success(releasedDocumentReleaseBOList);
            }
            if (!CollectionUtils.isEmpty(notExistDocumentReleaseBOList)) {
                return Result.ofNotFound("存在未查询到的文件", notExistDocumentReleaseBOList);
            }
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> getRelease(ListFolderRequest request) {
        Result<GetRepositoryResponse> releaseRepositoryInfo = repositoryClient.getReleaseRepositoryInfo();
        if (!releaseRepositoryInfo.wasSuccess()) {
            return Result.ofErrorData("初始化知识库失败");
        }
        GetRepositoryResponse repositoryInfoData = releaseRepositoryInfo.getData();
        Long repositoryId = repositoryInfoData.getRepositoryId();
        DocumentReleaseCheckQuery documentReleaseCheckQuery;
        if (userClient.isInRole(IsInRoleRequest.builder().includeRoleCodeList(Collections.singletonList(RoleConstant.QA)).ownership(IsInRoleRequest.Ownership.ONE_IN_ROLE.getCode()).build()).getData()) {
            documentReleaseCheckQuery = DocumentReleaseCheckQuery.builder()
                    .repositoryId(repositoryId)
                    .folderId(request.getParentFolderId()).build();
        } else {
            documentReleaseCheckQuery = DocumentReleaseCheckQuery.builder()
                    .repositoryId(repositoryId)
                    .checkUserId(UserContextHolder.getUserId())
                    .folderId(request.getParentFolderId()).build();
        }

        List<DocumentReleaseCheckBO> documentReleaseCheckBOList = documentReleaseCheckManager.listDocumentReleaseCheckByRepositoryIdAndSourceFolderId(documentReleaseCheckQuery);
        if (CollectionUtils.isEmpty(documentReleaseCheckBOList)) {
            return Result.success();
        }
        if (!CollectionUtils.isEmpty(documentReleaseCheckBOList)) {
            Set<Long> documentReleaseIdSet = documentReleaseCheckBOList.stream().map(DocumentReleaseCheckBO::getDocumentReleaseId).collect(Collectors.toSet());
            DocumentReleaseQuery query = DocumentReleaseQuery.max()
                    .documentReleaseIdS(documentReleaseIdSet)
                    .documentCode(request.getDocumentCode())
                    .documentLevel(request.getDocumentLevel())
                    .effectFlag(true)
                    .documentProperty(request.getDocumentProperty())
                    .build();
            List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager.listDocumentRelease(query);
            if (!CollectionUtils.isEmpty(documentReleaseBOList)) {
                Set<Long> documentIds = documentReleaseBOList.stream().map(DocumentReleaseBO::getDocumentId).collect(Collectors.toSet());
                Map<Long, String> map = new HashMap<>();
                if (!CollectionUtils.isEmpty(documentIds)) {
                    map.putAll(documentClient.listDocumentById(documentIds).getData().stream().collect(Collectors.toMap(GetDocumentResponse::getDocumentId, GetDocumentResponse::getFileExtension)));
                }

                Map<String, String> documentInfoMap = dictClient.listDictItem(
                        ListDictItemRequest.builder().pageSize(1000).dictGroupCodes(
                                Collections.singletonList("document_category")).build()).getData().stream().collect(Collectors.toMap(ListDictItemResponse::getDictCode, ListDictItemResponse::getDictValue));
                documentReleaseBOList.forEach(e -> {
                    e.setDocumentLevelName(documentInfoMap.get(String.valueOf(e.getDocumentLevel())));
                    e.setDocumentPropertyName(documentInfoMap.get(e.getDocumentProperty()));
                    if (map.containsKey(e.getDocumentId())) {
                        e.setFileExtension(map.get(e.getDocumentId()));
                    }
                });
                documentReleaseBOList.sort(Comparator.comparing(DocumentReleaseBO::getDocumentCode).reversed());
                return Result.success(documentReleaseBOList);
            }
        }
        return Result.success();
    }

    /**
     * 获取发行文件
     * @param documentReleaseId
     * @return
     */
    @Override
    public DocumentReleaseBO getDocumentRelease(Long documentReleaseId) {
        return documentReleaseManager.getDocumentRelease(documentReleaseId);
    }

    @Override
    public Result<?> getDocumentListByType(ListDocumentByTypeRequest request) {
        Result<List<GetDocumentResponse>> listResult = documentClient.listDocument(ListDocumentRequest.builder()
                .pageIndex(0)
                .pageSize(1000)
                .type(request.getType())
                .build());
        if (!listResult.wasSuccess()) {
            return Result.ofBadRequest("获取文档失败");
        }
        return Result.success(listResult.getData());
    }

    /**
     * 更新发行状态
     *
     */
    @Override
    public Result<?> changeStatus() {
        //查找所有生效或未生效文件
        List<DocumentReleaseBO> documentReleaseBOList = documentReleaseManager
                .listDocumentRelease(
                        DocumentReleaseQuery.max().status(0).build().addEffectFlag(true).addEffectFlag(false));
        List<DocumentReleaseBO> effectDocumentList = documentReleaseBOList
                .stream().filter(DocumentReleaseBO::getEffectFlag).collect(Collectors.toList());
        documentReleaseBOList.removeIf(e -> !e.getEffectFlag());
        Set<Long> effectDocumentIdList = documentReleaseBOList
                .stream()
                .filter(e -> e.getEffectDate().isBefore(LocalDate.now().plusDays(+1)))
                .map(DocumentReleaseBO::getDocumentReleaseId)
                .collect(Collectors.toSet());
        Set<Long> failureDocumentIdList = effectDocumentList
                .stream()
                .filter(e -> Objects.nonNull(e.getFailureDate()) && LocalDate.now().isAfter(e.getFailureDate()))
                .map(DocumentReleaseBO::getDocumentReleaseId)
                .collect(Collectors.toSet());
        int row = 0;
        if (!CollectionUtils.isEmpty(effectDocumentIdList)) {
            row += documentReleaseManager
                    .takeEffectFlagDocumentReleaseById(
                            DocumentReleaseQuery.max().documentReleaseIdS(effectDocumentIdList).build());
        }
        if (!CollectionUtils.isEmpty(failureDocumentIdList)) {
            row += documentReleaseManager
                    .loseEffectFlagDocumentReleaseById(
                            DocumentReleaseQuery.max().documentReleaseIdS(failureDocumentIdList).build());
        }
        return Result.success(row);
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/28 10:15
     * @param userDTOS
     * @return java.util.List<com.xy.biz.xd.domain.resp.DocumentReleaseByUserResponse>
     * @description 构建签收人员列表
     */
    private List<DocumentReleaseByUserResponse> buildCheckUsers(List<UserDTO> userDTOS, Set<Long> docRelIds) {
        List<DocumentReleaseByUserResponse> documentReleaseByUserResponseList = new ArrayList<>();
        //根据发行ID查发行确认表
        Map<Long, List<DocumentReleaseCheckBO>> checkMap = documentReleaseCheckManager.listDocumentReleaseCheckByReleaseId(docRelIds).stream().collect(Collectors.groupingBy(DocumentReleaseCheckBO::getCheckUserId));
        for (UserDTO u : userDTOS) {
            DocumentReleaseByUserResponse documentReleaseByUserResponse = new DocumentReleaseByUserResponse();
            documentReleaseByUserResponse.setId(u.getUserId());
            documentReleaseByUserResponse.setLabel(u.getUserName());
            if (checkMap.containsKey(u.getUserId())) {
                documentReleaseByUserResponse.setSignForStatus(1);
                documentReleaseByUserResponse.setSignForTime(checkMap.get(u.getUserId()).get(0).getCheckTime());
                documentReleaseByUserResponse.setSignForTimeString(CalendarUtils.getDeadlineString(checkMap.get(u.getUserId()).get(0).getCheckTime(), LocalDateTime.now()));
                documentReleaseByUserResponse.setSelfStudy(checkMap.get(u.getUserId()).get(0).getLearnFlag());
            } else {
                documentReleaseByUserResponse.setSignForStatus(0);
                documentReleaseByUserResponse.setSelfStudy(false);
            }
            documentReleaseByUserResponseList.add(documentReleaseByUserResponse);
        }
        return documentReleaseByUserResponseList;
    }

}
